package com.controller.User;

import com.entity.Login;
import com.entity.UserInfo;
import com.entity.UserRole;
import com.iflytek.face.WebFaceCompare;
import com.service.LoginService;
import com.service.Sendsms;
import com.service.UserInfoService;
import com.service.UserRoleService;
import com.util.*;
import com.vo.ResultVo;
import com.vo.SmsBean;

import net.sf.json.JSONObject;
import sun.misc.BASE64Decoder;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  登录注册 控制器
 * </p>
 *
 * @author hlt
 * @since 2019-12-21
 */
@Controller
public class LoginController {
    @Autowired
    private LoginService loginService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private Sendsms sendsms;
    @Autowired
    private WebFaceCompare webFace;
    
    /**手机号和注册验证码map集合*/
    private static Map<String, String> phonecodemap1 = new HashMap<>();
    /**手机号和重置密码验证码map集合*/
    private static Map<String, String> phonecodemap2 = new HashMap<>();
    /**
     *图片验证码
     * */
    @RequestMapping(value = "/images", method = {RequestMethod.GET, RequestMethod.POST})
    public void images(HttpServletResponse response) throws IOException {
        response.setContentType("image/jpeg");
        //禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        ValidateCode vCode = new ValidateCode(820, 200, 5, 8000);
        vCode.write(response.getOutputStream());
    }
    
    
    /**注册时发送短信验证码
     * 1.判断是否为注册类型验证码
     * 2.判断手机号格式是否正确
     * 3.判断手机号是否已经注册过
     * 4.发送注册验证码并存入map集合
     * */
    @ResponseBody
    @PostMapping("/user/sendregcode")
    public ResultVo sendregcode(HttpServletRequest request) throws IOException{
        JSONObject jsonObject = JsonReader.receivePost(request);
        final String mobilephone = jsonObject.getString("mobilephone");
        Integer type = jsonObject.getInt("type");
        Login login = new Login();
        if(type!=0){
            return new ResultVo(false,StatusCode.ACCESSERROR,"违规操作");
        }
        if (!JustPhone.justPhone(mobilephone)) {//判断输入的手机号格式是否正确
            return new ResultVo(false,StatusCode.ERROR,"请输入正确格式的手机号");
        }
        //查询手机号是否已经注册
        login.setMobilephone(mobilephone);
        Login userIsExist = loginService.userLogin(login);
        if (!StringUtils.isEmpty(userIsExist)){//用户账号已经存在
            return new ResultVo(false, StatusCode.ERROR,"该手机号已经注册过了");
        }
        SmsBean reString = sendsms.getsms(mobilephone);
        if (reString.getStatus()==4051) {
        	phonecodemap1.put(mobilephone,reString.getData().toString());
        	return new ResultVo(true,StatusCode.SMS,"验证码发送成功");
		}
        return new ResultVo(false,StatusCode.REMOTEERROR,"验证码发送失败");    
    }

    /**注册
     * 1.前端传入用户名（username）、密码（password）、邮箱（email）、手机号（mobilephone）、验证码（vercode）
     * 2.查询账号是否已经注册
     * 3.查询用户名是否已存在
     * 4.判断验证码是否有效或正确
     * 5.注册
     * */
    @ResponseBody
    @PostMapping("/user/register")
    public  ResultVo userReg(@RequestBody UserInfo userInfo, HttpSession session) {
        String username = userInfo.getUsername();
        String password = userInfo.getPassword();
        String mobilephone = userInfo.getMobilephone();
        String vercode = userInfo.getVercode();
        Login login = new Login();
        login.setMobilephone(mobilephone);
        //查询账号是否已经注册
        Login userIsExist = loginService.userLogin(login);
        if (!StringUtils.isEmpty(userIsExist)){//用户账号已经存在
            return new ResultVo(false, StatusCode.ERROR,"该用户已经注册过了");
        }
        login.setUsername(username);
        login.setMobilephone(null);
        Login userNameIsExist = loginService.userLogin(login);
        if (!StringUtils.isEmpty(userNameIsExist)){//用户名已经存在
            return new ResultVo(false, StatusCode.ERROR,"用户名已存在，请换一个吧");
        }
        String rel = phonecodemap1.get(mobilephone);
        if (StringUtils.isEmpty(rel)) {//验证码到期 或者 没发送短信验证码
            return new ResultVo(false,StatusCode.ERROR,"请重新获取验证码");
        }
        if (rel.equalsIgnoreCase(vercode)) {//验证码正确
            //盐加密
            String passwords = new Md5Hash(password, "Campus-shops").toString();
            String userid = KeyUtil.genUniqueKey();
            login.setId(KeyUtil.genUniqueKey());
            login.setUserid(userid);
            login.setMobilephone(mobilephone);
            login.setPassword(passwords);
            Integer integer = loginService.loginAdd(login);
            
            
            //新注册用户存入默认头像、存入默认签名
            userInfo.setUserid(userid);
            userInfo.setPassword(passwords);
            userInfo.setUimage("/pic/xz.png");
            userInfo.setSign("如此清秋何吝酒，这般明月不须钱");
            userInfo.setStatus("offline");
            Integer integer1 = userInfoService.userReg(userInfo);
            if (integer==1 && integer1==1){
                /**注册成功后存入session*/
                session.setAttribute("userid",userid);
                session.setAttribute("username",username);
                /**存入用户角色信息*/
                UserRole userrole = new UserRole();
                userrole.setUserid(userid);
                userrole.setRoleid(1);
                userrole.setIdentity("网站用户");
                userRoleService.InsertUserRole(userrole);        
                return new ResultVo(true,StatusCode.OK,"注册成功");
            }
            return new ResultVo(false,StatusCode.ERROR,"注册失败");
        }
        return new ResultVo(false,StatusCode.ERROR,"验证码错误");
    }

    /**登录
     * 1.判断输入账号的类型
     * 2.登录
     * */
    @ResponseBody
    @PostMapping("/user/login")
    public ResultVo userLogin(@RequestBody Login login, HttpSession session){
        String account=login.getUsername();
        String password=login.getPassword();
        String vercode=login.getVercode();
        if(!ValidateCode.code.equalsIgnoreCase(vercode)){
            return new ResultVo(false,StatusCode.ERROR,"请输入正确的验证码");
        }
        //判断输入的账号是否手机号
        if (!JustPhone.justPhone(account)) {
            //输入的是用户名
            String username = account;       
        }else {
            //输入的是手机号
            String mobilephone = account;
            login.setMobilephone(mobilephone);
            //将封装的login中username变为null
            login.setUsername(null);            
        }
        try {    
        	//验证登录部分
            Login login1 = loginService.userLogin(login);     
            if (login1 != null)
            {	
            	String pwString=new Md5Hash(password, "Campus-shops").toString();
                if (login1.getPassword().equals(pwString))
                {
                	session.setAttribute("userid",login1.getUserid());
                    session.setAttribute("username",login1.getUsername());
                    return new ResultVo(true,StatusCode.OK,"登录成功");
                }
                else {
                	return new ResultVo(true,StatusCode.ERROR,"登录失败密码错误");
                }
            }
            else
            {
            	return new ResultVo(true,StatusCode.ERROR,"用户不存在");
            }  
        }catch (UnknownAccountException e){
            return new ResultVo(true,StatusCode.LOGINERROR,"用户名不存在");
        }catch (IncorrectCredentialsException e){
            return new ResultVo(true,StatusCode.LOGINERROR,"密码错误");
        }
    }
    
	/* 手机验证码登录 */
    @ResponseBody
    @PostMapping("/user/loginbyphone")
    public ResultVo userLoginbyphone(@RequestBody Login login, HttpSession session){
        String mobilephone=login.getMobilephone();
        String vercode=login.getVercode();        
        String rel = phonecodemap1.get(mobilephone); 
        if (StringUtils.isEmpty(rel)) {//验证码到期 或者 没发送短信验证码
            return new ResultVo(false,StatusCode.ERROR,"请重新获取验证码");
        }
        if (rel.equalsIgnoreCase(vercode)) {//验证码正确              	
        	Login login1 = loginService.userLogin(login);
        	System.err.println(login1);
        	if(login1==null) {
        		return new ResultVo(true,StatusCode.ERROR,"登录失败，账号不存在");
        	}else {
	            session.setAttribute("userid",login1.getUserid());
	            session.setAttribute("username",login1.getUsername());
	            return new ResultVo(true,StatusCode.OK,"登录成功");
        	}   
            }
        return new ResultVo(false,StatusCode.ERROR,"失败，验证码错误");
        
    }

    /**重置密码时发送短信验证码
     * 1.判断是否为重置密码类型验证码
     * 2.判断手机号格式是否正确
     * 3.查询账号是否存在
     * 4.发送验证码
     * */
    @ResponseBody
    @PostMapping("/user/sendresetpwd")
    public ResultVo sendresetpwd(HttpServletRequest request) throws IOException {
        JSONObject json = JsonReader.receivePost(request);
        final String mobilephone = json.getString("mobilephone");
        Integer type = json.getInt("type");
        Login login = new Login();
        if(type!=1){
            return new ResultVo(false,StatusCode.ACCESSERROR,"违规操作");
        }
        if (!JustPhone.justPhone(mobilephone)) {//判断输入的手机号格式是否正确
            return new ResultVo(false,StatusCode.ERROR,"请输入正确格式的手机号");
        }
        //查询手机号是否存在
        login.setMobilephone(mobilephone);
        Login userIsExist = loginService.userLogin(login);
        if (StringUtils.isEmpty(userIsExist)){//用户账号不存在
            return new ResultVo(false, StatusCode.LOGINERROR,"该用户不存在");
        }
        String code = GetCode.phonecode();
        SmsBean reString = sendsms.getsms(mobilephone);//发送验证码
        
        return new ResultVo(false,StatusCode.REMOTEERROR,"验证码发送失败");
    }

    /**重置密码
     * 1.判断手机号格式是否正确
     * 2.查询手机号是否存在
     * 3.判断验证码是否有效或正确
     * 4.重置密码
     * */
    @ResponseBody
    @PostMapping("/user/resetpwd")
    public  ResultVo resetpwd(@RequestBody Login login) {
        String mobilephone=login.getMobilephone();
        String password=login.getPassword();
        String vercode=login.getVercode();
        Login login1 = new Login();
        UserInfo userInfo = new UserInfo();
        if (!JustPhone.justPhone(mobilephone)) {//判断输入的手机号格式是否正确
            return new ResultVo(false,StatusCode.ERROR,"请输入正确格式的手机号");
        }
        //查询手机号是否存在
        login1.setMobilephone(mobilephone);
        Login userIsExist = loginService.userLogin(login1);
        if (StringUtils.isEmpty(userIsExist)){//用户账号不存在
            return new ResultVo(false, StatusCode.LOGINERROR,"该账号不存在");
        }
        String rel = phonecodemap2.get(mobilephone);
        if (StringUtils.isEmpty(rel)) {//验证码到期 或者 没发送短信验证码
            return new ResultVo(false,StatusCode.ERROR,"请重新获取验证码");
        }
        if (rel.equalsIgnoreCase(vercode)) {//验证码正确
            userInfo.setMobilephone(mobilephone);
            userInfo.setPassword(password);
            userInfo.setUserid(userIsExist.getUserid());       
            Integer integer1 = userInfoService.UpdateUserInfo(userInfo);
            if (!StringUtils.isEmpty(userIsExist)){//用户账号已经存在
            	SmsBean reString = sendsms.getsms(mobilephone);
    	        if (reString.getStatus()==4051) {
    	        	System.err.println("验证码："+reString.getData().toString());
    	        	phonecodemap1.put(mobilephone,reString.getData().toString());
    	        	return new ResultVo(true,StatusCode.SMS,"验证码发送成功");
    			}
            }else{
    	        return new ResultVo(false, StatusCode.ERROR,"该手机号未注册");
            };
            return new ResultVo(false,StatusCode.ERROR,"重置密码失败");
        }
        return new ResultVo(false,StatusCode.ERROR,"验证码错误");
    }

    /**退出登陆*/
    @GetMapping("/user/logout")
    public String logout(HttpServletRequest request,HttpSession session){
        String userid = (String)session.getAttribute("userid");
        String username = (String)session.getAttribute("username");
        if(StringUtils.isEmpty(userid) && StringUtils.isEmpty(username)){
            return "redirect:/";
        }
        request.getSession().removeAttribute("userid");
        request.getSession().removeAttribute("username");
        return "redirect:/";
    }
    
    /**
     	* 用户通过手机验证码登录获取验证码接口
     *
     */
    @ResponseBody
    @PostMapping("/user/sendlogcode")
    public ResultVo sendlogcode(HttpServletRequest request) throws IOException{
        JSONObject jsonObject = JsonReader.receivePost(request);
        final String mobilephone = jsonObject.getString("mobilephone");
        Integer type = jsonObject.getInt("type");
        Login login = new Login();
        if(type!=0){
            return new ResultVo(false,StatusCode.ACCESSERROR,"违规操作");
        }
        if (!JustPhone.justPhone(mobilephone)) {//判断输入的手机号格式是否正确
            return new ResultVo(false,StatusCode.ERROR,"请输入正确格式的手机号");
        }
        //查询手机号是否已经注册
        login.setMobilephone(mobilephone);
        Login userIsExist = loginService.userLogin(login);
        if (!StringUtils.isEmpty(userIsExist)){//用户账号已经存在
        	SmsBean reString = sendsms.getsms(mobilephone);
	        if (reString.getStatus()==4051) {
	        	System.err.println("验证码："+reString.getData().toString());
	        	phonecodemap1.put(mobilephone,reString.getData().toString());
	        	return new ResultVo(true,StatusCode.SMS,"验证码发送成功");
			}
        }else{
	        return new ResultVo(false, StatusCode.ERROR,"该手机号未注册");
        };
        return new ResultVo(false,StatusCode.REMOTEERROR,"验证码发送失败");       
    }
    
    /**
     * 人脸识别登录接口
     * */
    @PostMapping("/face")   
    public String face(HttpServletRequest request) throws IllegalStateException, IOException {  	
    		
		    //默认传入的参数带类型等参数：data:image/png;base64,
		    //获取到图片datastring类型
		    String imgStr = request.getParameter("imgData");
		    String userphone = request.getParameter("userphone");
	    	//对字符串处理
		    if (null != imgStr) {
		        imgStr = imgStr.substring(imgStr.indexOf(",") + 1);
		    }
		    //对inmStr进行解码
		    byte[] imgbyte = GenerateImage(imgStr);
		    
		    //图片转码成功以后验证登录
		    if (imgbyte != null) {
		    	try {
					this.webFace.face(imgbyte, "C:\\Users\\Lenovo\\Desktop\\1.jpg");
					return "0";
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return "0";
				}
		    	
		    }else {
		    	
		    	return "0";
		    }
		    
    	
    }
    //Base64解码后获取二进制数组
    public byte[] GenerateImage(String imgStr) {
	    try {
	        if (imgStr == null) {
	            return null;
	        }
	        BASE64Decoder decoder = new BASE64Decoder();
	        //Base64解码转换成二进制数组后返回
	        byte[] b = decoder.decodeBuffer(imgStr);
			/*
			 * //如果目录不存在，则创建 File file = new File(filePath); if (!file.exists()) {
			 * file.mkdirs(); } //生成图片 FileOutputStream out = new FileOutputStream(filePath
			 * + fileName); out.write(b); out.flush(); out.close(); return true;
			 */
	        return b;
	    } catch (Exception e) {
	        return null;
	    }
	}

}